package com.kitty.cross.core.client;

import com.kitty.common.utils.SpringUtils;
import com.kitty.cross.CrossServerConfig;
import com.kitty.cross.core.server.BaseCMessageDispatcher;
import com.kitty.cross.core.server.CMessageDispatcher;

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
//后加


@Component
public class C2SSessionPoolFactory {

	private GenericObjectPoolConfig config;
	
	private ConcurrentMap<String, GenericObjectPool<CCSession>> pools = new ConcurrentHashMap<>();
	
	private static volatile C2SSessionPoolFactory self;

	@PostConstruct
	private void init() {
		config = new GenericObjectPoolConfig();
		config.setMaxTotal(Runtime.getRuntime().availableProcessors());
		config.setMaxWaitMillis(5000);

		self = this;
	}

	public static C2SSessionPoolFactory getInstance() {
		return self;
	}

	public CCSession borrowSession(String ip, int port) {
		String key = buildKey(ip, port);
		try {
			C2SSessionFactory factory = new C2SSessionFactory(ip, port);
			GenericObjectPool<CCSession> pool = pools.getOrDefault(key, new GenericObjectPool(factory, config));
			pools.putIfAbsent(key, pool);
			return pool.borrowObject();
		} catch (Exception e) {

			return null;
		}
	}

	public CCSession borrowCrossSession() {
		CrossServerConfig config = SpringUtils.getBean(CrossServerConfig.class);
		String ip = config.getCenterIp();
		int port = config.getCenterPort();
		return borrowSession(ip, port);
	}

	public void returnSession(CCSession session) {
		String key = buildKey(session.getIpAddr(), session.getPort());
		GenericObjectPool<CCSession> pool = pools.get(key);
		if (pool != null) {
			pool.returnObject(session);
		}
	}
	
	private String buildKey(String ip, int port) {
		return  ip + "-" + port;
	}
}

class C2SSessionFactory extends BasePooledObjectFactory<CCSession> {

	String ip;

	int port;

	CMessageDispatcher dispatcher;

	public C2SSessionFactory(String ip, int port) {
		super();
		this.ip = ip;
		this.port = port;
		this.dispatcher = BaseCMessageDispatcher.getInstance();
	}

	public String getIp() {
		return ip;
	}

	public void setIp(String ip) {
		this.ip = ip;
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	@Override
	public CCSession create() throws Exception {
		CCSession session = CCSession.valueOf(ip, port, dispatcher);
		session.buildConnection();
		return session;
	}

	@Override
	public PooledObject<CCSession> wrap(CCSession obj) {
		return new DefaultPooledObject<CCSession>(obj);
	}

}
